import socket
import threading
import time
import logging
import os
import struct
import random
import subprocess
import tempfile

logger = logging.getLogger('MediaStreamer')

class MediaStreamer:
    def __init__(self, config):
        self.config = config
        self.running = False
        self.client_socket = None
        self.tcp_server = None
        self.server_thread = None
        self.stream_thread = None
        # 参考标准实现：随机初始化RTP参数
        self.ssrc = random.randint(100000, 999999)
        self.seq = random.randint(1000, 9999)
        self.timestamp = random.randint(100000, 999999)
        
        # 改进的时间戳管理 - 使用单调递增，避免倒退
        self.rtp_timestamp = random.randint(100000, 999999)
        self.frame_duration = 3600  # 25fps: 90000Hz / 25 = 3600 ticks/frame
        self.current_frame_timestamp = self.rtp_timestamp  # 当前帧时间戳
        self.last_frame_timestamp = 0
        self.mtu = 1400  # 最大传输单元，留出一些余量
        
        # 仅在TCP被动模式时启动TCP服务器
        if getattr(self.config, 'tcp_passive', False):
            self.start_tcp_server()
        else:
            logger.info("使用UDP主动模式，无需启动TCP服务器")
    
    def _extract_h264_from_mp4(self, mp4_file):
        """从MP4文件中提取H.264数据"""
        try:
            logger.info(f"开始从MP4提取H.264数据: {mp4_file}")
            
            # 检查文件是否存在
            if not os.path.exists(mp4_file):
                logger.error(f"MP4文件不存在: {mp4_file}")
                return None
            
            file_size = os.path.getsize(mp4_file)
            logger.info(f"MP4文件大小: {file_size:,} 字节")
            
            # 首先检查ffmpeg是否可用
            try:
                subprocess.run(["ffmpeg", "-version"], capture_output=True, timeout=5)
            except (FileNotFoundError, subprocess.TimeoutExpired):
                logger.error("ffmpeg未安装或不可用，无法处理MP4文件")
                logger.info("建议：安装ffmpeg或使用H.264文件")
                return None
            
            # 使用ffmpeg从MP4中提取H.264原始数据
            h264_file = tempfile.NamedTemporaryFile(suffix='.h264', delete=False)
            h264_file.close()
            
            # 使用ffmpeg命令提取H.264流
            cmd = [
                'ffmpeg', '-i', mp4_file,
                '-c:v', 'copy',  # 直接复制视频流，不重新编码
                '-bsf:v', 'h264_mp4toannexb',  # 转换为Annex B格式
                '-f', 'h264',  # 输出格式为H.264原始流
                '-y',  # 覆盖输出文件
                h264_file.name
            ]
            
            logger.info(f"执行ffmpeg命令: {' '.join(cmd)}")
            
            # 执行ffmpeg命令
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
            
            if result.returncode == 0:
                if os.path.exists(h264_file.name):
                    h264_size = os.path.getsize(h264_file.name)
                    logger.info(f"成功提取H.264数据，大小: {h264_size:,} 字节")
                    
                    # 验证H.264格式
                    with open(h264_file.name, 'rb') as f:
                        header = f.read(8)
                        if header.startswith(b'\x00\x00\x00\x01') or header.startswith(b'\x00\x00\x01'):
                            logger.info("✓ H.264格式验证通过（找到NAL起始码）")
                        else:
                            logger.warning("H.264格式可能有问题（未找到标准NAL起始码）")
                    
                    # 读取提取的H.264数据
                    with open(h264_file.name, 'rb') as f:
                        h264_data = f.read()
                    
                    # 清理临时文件
                    os.unlink(h264_file.name)
                    
                    logger.info(f"H.264数据读取完成，返回 {len(h264_data):,} 字节")
                    return h264_data
                else:
                    logger.error("H.264临时文件未生成")
                    return None
            else:
                logger.error(f"ffmpeg提取失败，返回码: {result.returncode}")
                logger.error(f"错误信息: {result.stderr}")
                if h264_file.name and os.path.exists(h264_file.name):
                    os.unlink(h264_file.name)
                return None
                
        except subprocess.TimeoutExpired:
            logger.error("ffmpeg命令执行超时（60秒）")
            return None
        except Exception as e:
            logger.error(f"MP4文件处理失败: {e}")
            return None
    
    def _find_fallback_video_file(self, video_file):
        """查找备用视频文件"""
        base_dir = os.path.dirname(video_file)
        
        # 查找H.264文件
        h264_files = []
        for file in os.listdir(base_dir):
            if file.lower().endswith('.h264'):
                h264_files.append(os.path.join(base_dir, file))
        
        if h264_files:
            # 优先选择recordfile01.h264
            for h264_file in h264_files:
                if 'recordfile01' in os.path.basename(h264_file).lower():
                    logger.info(f"找到备用H.264文件: {h264_file}")
                    return h264_file
            
            # 否则使用第一个找到的H.264文件
            logger.info(f"找到备用H.264文件: {h264_files[0]}")
            return h264_files[0]
        
        return None
    
    def _get_video_data(self, video_file):
        """根据文件扩展名获取视频数据"""
        file_ext = os.path.splitext(video_file)[1].lower()
        logger.info(f"处理视频文件: {video_file}, 格式: {file_ext}")
        
        if file_ext == '.mp4':
            logger.info("检测到MP4文件，开始提取H.264数据")
            h264_data = self._extract_h264_from_mp4(video_file)
            
            if h264_data:
                logger.info(f"MP4处理成功，H.264数据大小: {len(h264_data):,} 字节")
                return h264_data
            else:
                logger.error("MP4文件H.264提取失败")
                
                # 尝试查找备用H.264文件
                logger.info("正在查找备用H.264文件...")
                fallback_file = self._find_fallback_video_file(video_file)
                
                if fallback_file:
                    logger.info(f"使用备用文件: {fallback_file}")
                    try:
                        with open(fallback_file, 'rb') as f:
                            h264_data = f.read()
                        logger.info(f"备用H.264文件读取成功，大小: {len(h264_data):,} 字节")
                        return h264_data
                    except Exception as e:
                        logger.error(f"备用H.264文件读取失败: {e}")
                
                logger.error("无法获取任何视频数据")
                return None
                
        elif file_ext == '.h264':
            logger.info("检测到H.264文件，直接读取")
            try:
                with open(video_file, 'rb') as f:
                    h264_data = f.read()
                logger.info(f"H.264文件读取成功，大小: {len(h264_data):,} 字节")
                return h264_data
            except Exception as e:
                logger.error(f"H.264文件读取失败: {e}")
                return None
        else:
            logger.error(f"不支持的文件格式: {file_ext}")
            return None

    def start_tcp_server(self):
        """启动TCP服务器监听连接"""
        try:
            self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.tcp_server.bind((self.config.local_ip, self.config.tcp_media_port))
            self.tcp_server.listen(1)
            
            logger.info(f"TCP服务器启动在 {self.config.local_ip}:{self.config.tcp_media_port}")
            
            # 在单独线程中处理连接
            self.server_thread = threading.Thread(target=self._handle_tcp_connections, daemon=True)
            self.server_thread.start()
            
        except Exception as e:
            logger.error(f"TCP服务器启动失败: {e}")
            self.tcp_server = None

    def _handle_tcp_connections(self):
        """处理TCP连接"""
        while self.running:
            try:
                client_socket, addr = self.tcp_server.accept()
                logger.info(f"TCP连接来自: {addr}")
                
                # 创建一个新的线程来处理客户端请求
                client_handler = threading.Thread(target=self._handle_tcp_client, args=(client_socket, addr), daemon=True)
                client_handler.start()
                
            except Exception as e:
                logger.error(f"TCP连接处理失败: {e}")
                if not self.running:
                    break
                time.sleep(0.1) # 短暂休眠，避免CPU占用过高

    def _handle_tcp_client(self, client_socket, addr):
        """处理单个TCP客户端的请求"""
        try:
            # 接收客户端发送的SSRC
            ssrc_data = client_socket.recv(12)
            if len(ssrc_data) != 12:
                logger.error(f"TCP客户端 {addr} 发送的SSRC数据长度错误: {len(ssrc_data)}")
                client_socket.close()
                return
            
            ssrc = struct.unpack("!I", ssrc_data)[0]
            logger.info(f"TCP客户端 {addr} 提供的SSRC: 0x{ssrc:08x}")
            
            # 更新MediaStreamer的SSRC
            self.ssrc = ssrc
            
            # 发送确认消息
            ack_msg = "SSRC_ACK"
            client_socket.send(ack_msg.encode())
            
            # 接收客户端发送的RTP端口
            rtp_port_data = client_socket.recv(2)
            if len(rtp_port_data) != 2:
                logger.error(f"TCP客户端 {addr} 发送的RTP端口数据长度错误: {len(rtp_port_data)}")
                client_socket.close()
                return
            
            rtp_port = struct.unpack("!H", rtp_port_data)[0]
            logger.info(f"TCP客户端 {addr} 提供的RTP端口: {rtp_port}")
            
            # 发送确认消息
            ack_msg = "RTP_PORT_ACK"
            client_socket.send(ack_msg.encode())
            
            # 启动流线程
            self.stream_thread = threading.Thread(target=self._stream_tcp, args=(client_socket, addr, rtp_port), daemon=True)
            self.stream_thread.start()
            
        except Exception as e:
            logger.error(f"TCP客户端 {addr} 处理失败: {e}")
            client_socket.close()

    def start_stream(self, target_ip=None, target_port=None, ssrc=None):
        """开始媒体流"""
        if self.running:
            logger.warning("视频流已经在运行中")
            return
            
        self.running = True
        # 使用WVP提供的SSRC，但保持原有的seq和timestamp
        if ssrc:
            self.ssrc = ssrc
        logger.info("视频流开始")
        
        if self.config.tcp_passive:
            # TCP被动模式流
            logger.info("启动TCP被动模式推流")
            self.stream_thread = threading.Thread(target=self._stream_tcp, daemon=True)
        else:
            # UDP模式流
            logger.info(f"启动UDP主动模式推流，目标: {target_ip}:{target_port}, SSRC: 0x{self.ssrc:08x}")
            self.stream_thread = threading.Thread(target=self._stream_udp, args=(target_ip, target_port), daemon=True)
            
        self.stream_thread.start()
        logger.info("推流线程已启动")
    
    def stop_stream(self):
        """停止媒体流"""
        if not self.running:
            logger.warning("视频流已经停止")
            return
            
        self.running = False
        logger.info("视频流停止")
        
        # 等待推流线程结束
        if hasattr(self, 'stream_thread') and self.stream_thread.is_alive():
            logger.info("等待推流线程结束...")
            self.stream_thread.join(timeout=5)
            if self.stream_thread.is_alive():
                logger.warning("推流线程未能正常结束")
            else:
                logger.info("推流线程已结束")
    
    def _stream_udp(self, target_ip, target_port):
        """UDP流推送 - 支持MP4和H.264文件"""
        if not target_ip or not target_port:
            logger.error("UDP流目标IP或端口为空")
            return
            
        target = (target_ip, target_port)
        logger.info(f"标准H.264 RTP推流目标: {target}, SSRC: 0x{self.ssrc:08x}")
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        try:
            # 设置socket选项提高稳定性
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 1024)
            
            # 检查视频文件是否存在
            video_file = os.path.join(os.path.dirname(__file__), os.path.basename(self.config.video_file))
            if not os.path.exists(video_file):
                logger.error(f"视频文件不存在: {video_file}")
                return
            
            logger.info(f"开始循环播放视频文件: {video_file}")
            
            # 循环播放文件
            cycle_count = 0
            while self.running:
                try:
                    logger.info(f"开始第 {cycle_count + 1} 次循环播放")
                    
                    # 获取视频数据（支持MP4和H.264）
                    h264_data = self._get_video_data(video_file)
                    if not h264_data:
                        logger.error("无法获取视频数据")
                        break
                    
                    nal_units = self._parse_h264_nal_units(h264_data)
                    if not nal_units:
                        logger.error("无法解析H.264数据中的NAL单元")
                        break
                    
                    # 发送这一轮的NAL单元
                    success = self._send_h264_rtp_cycle(sock, target, nal_units, cycle_count)
                    if not success:
                        logger.warning("发送循环中断")
                        break
                    
                    cycle_count += 1
                    
                    # 循环间隔，模拟视频重新开始
                    if self.running:
                        time.sleep(0.1)  # 100ms间隔
                        
                except Exception as e:
                    logger.error(f"循环播放出错: {e}")
                    break
                    
        except Exception as e:
            logger.error(f"UDP推流失败: {e}")
        finally:
            sock.close()
            logger.info("UDP连接已关闭")

    def _stream_tcp(self, client_socket, addr, rtp_port):
        """TCP流推送 - 支持MP4和H.264文件"""
        logger.info(f"TCP客户端 {addr} 连接成功，RTP端口: {rtp_port}")
        
        try:
            # 发送SSRC给客户端
            ssrc_bytes = struct.pack("!I", self.ssrc)
            client_socket.send(ssrc_bytes)
            
            # 发送RTP端口给客户端
            rtp_port_bytes = struct.pack("!H", rtp_port)
            client_socket.send(rtp_port_bytes)
            
            # 发送确认消息
            ack_msg = "TCP_STREAM_STARTED"
            client_socket.send(ack_msg.encode())
            
            # 检查视频文件是否存在
            video_file = os.path.join(os.path.dirname(__file__), os.path.basename(self.config.video_file))
            if not os.path.exists(video_file):
                logger.error(f"视频文件不存在: {video_file}")
                client_socket.close()
                return
            
            logger.info(f"开始循环播放视频文件: {video_file}")
            
            # 循环播放文件
            cycle_count = 0
            while self.running:
                try:
                    logger.info(f"开始第 {cycle_count + 1} 次循环播放")
                    
                    # 获取视频数据（支持MP4和H.264）
                    h264_data = self._get_video_data(video_file)
                    if not h264_data:
                        logger.error("无法获取视频数据")
                        break
                    
                    nal_units = self._parse_h264_nal_units(h264_data)
                    if not nal_units:
                        logger.error("无法解析H.264数据中的NAL单元")
                        break
                    
                    # 发送这一轮的NAL单元
                    success = self._send_h264_rtp_cycle(client_socket, rtp_port, nal_units, cycle_count)
                    if not success:
                        logger.warning("发送循环中断")
                        break
                    
                    cycle_count += 1
                    
                    # 循环间隔，模拟视频重新开始
                    if self.running:
                        time.sleep(0.1)  # 100ms间隔
                        
                except Exception as e:
                    logger.error(f"循环播放出错: {e}")
                    break
                    
        except Exception as e:
            logger.error(f"TCP推流失败: {e}")
        finally:
            client_socket.close()
            logger.info(f"TCP客户端 {addr} 连接已关闭")

    def stop_tcp_server(self):
        """停止TCP服务器"""
        if self.tcp_server:
            try:
                self.running = False
                self.tcp_server.close()
                logger.info("TCP服务器已停止")
            except Exception as e:
                logger.error(f"停止TCP服务器错误: {e}")
            finally:
                self.tcp_server = None

    def _send_h264_rtp_cycle(self, sock, target, nal_units, cycle_count):
        """发送一个完整的H.264文件循环"""
        packet_count = 0
        start_time = time.time()
        consecutive_errors = 0
        
        # 查找SPS和PPS
        sps_nal = None
        pps_nal = None
        
        for nal_type, nal_data in nal_units:
            if nal_type == 7:  # SPS
                sps_nal = nal_data
            elif nal_type == 8:  # PPS
                pps_nal = nal_data
        
        logger.info(f"开始发送H.264 RTP包 (循环{cycle_count + 1})，总计 {len(nal_units)} 个NAL单元")
        logger.info(f"目标地址: {target}, Socket类型: {type(sock)}")
        
        # 只在第一个循环开始时发送SPS/PPS，并连续发送多次确保接收
        if cycle_count == 0 and sps_nal and pps_nal:
            try:
                # 连续发送3次SPS/PPS确保可靠接收
                for i in range(3):
                    # 发送SPS
                    packet_count += 1
                    rtp_packet = self._create_rtp_packet(sps_nal, 7, packet_count, self.rtp_timestamp, marker_bit=False)
                    if hasattr(sock, 'sendto'):
                        sock.sendto(rtp_packet, target)
                    else:
                        sock.send(rtp_packet)
                    
                    # 发送PPS
                    packet_count += 1
                    rtp_packet = self._create_rtp_packet(pps_nal, 8, packet_count, self.rtp_timestamp, marker_bit=False)
                    if hasattr(sock, 'sendto'):
                        sock.sendto(rtp_packet, target)
                    else:
                        sock.send(rtp_packet)
                    
                    if i < 2:  # 前两次之间有间隔
                        time.sleep(0.005)  # 5ms间隔
                
                logger.debug(f"初始发送SPS/PPS完成 (重复3次), 时间戳: {self.rtp_timestamp}")
                
                # 短暂等待确保参数集被处理
                time.sleep(0.01)  # 10ms延迟
                
            except Exception as e:
                logger.error(f"发送初始SPS/PPS失败: {e}")
                consecutive_errors += 1
        
        # 发送视频数据帧
        frame_start_time = time.time()
        packets_in_frame = 0
        keyframe_count = 0
        
        for i, (nal_type, nal_data) in enumerate(nal_units):
            if nal_type in [7, 8]:  # 跳过SPS和PPS，只在必要时发送
                continue
                
            try:
                # 检查是否是关键帧(I帧)
                is_keyframe = (nal_type == 5)
                
                # 只在关键帧且距离上次发送SPS/PPS超过一定间隔时才重新发送
                if is_keyframe:
                    keyframe_count += 1
                    # 前5个关键帧都发送SPS/PPS，之后每10个关键帧发送一次
                    should_send_params = (keyframe_count <= 5) or (keyframe_count % 10 == 1)
                    if should_send_params and sps_nal and pps_nal:
                        # 发送SPS
                        packet_count += 1
                        rtp_packet = self._create_rtp_packet(sps_nal, 7, packet_count, self.rtp_timestamp, marker_bit=False)
                        if hasattr(sock, 'sendto'):
                            sock.sendto(rtp_packet, target)
                        else:
                            sock.send(rtp_packet)
                        logger.debug(f"GOP前发送SPS (NAL类型: 7), 大小: {len(rtp_packet)}, 时间戳: {self.rtp_timestamp}")
                        
                        # 发送PPS
                        packet_count += 1
                        rtp_packet = self._create_rtp_packet(pps_nal, 8, packet_count, self.rtp_timestamp, marker_bit=False)
                        if hasattr(sock, 'sendto'):
                            sock.sendto(rtp_packet, target)
                        else:
                            sock.send(rtp_packet)
                        logger.debug(f"GOP前发送PPS (NAL类型: 8), 大小: {len(rtp_packet)}, 时间戳: {self.rtp_timestamp}")
                        
                        # 短暂延迟
                        time.sleep(0.002)  # 减少到2ms延迟
                
                # 检查是否是新帧的开始（I帧或P帧）
                is_frame_start = (nal_type in [1, 5] and packets_in_frame == 0)
                if is_frame_start:
                    frame_start_time = time.time()
                    logger.debug(f"开始新帧 (NAL类型: {nal_type}), 时间戳: {self.rtp_timestamp}")
                
                # 如果NAL单元大于MTU，需要分包
                if len(nal_data) > self.mtu:
                    fragments = self._fragment_nal_unit(nal_data, nal_type)
                    logger.debug(f"NAL单元分片: {len(nal_data)} 字节 -> {len(fragments)} 个片段")
                    
                    for j, fragment in enumerate(fragments):
                        packet_count += 1
                        # 对于分片，使用FU-A类型(28)，最后一个分片设置marker bit
                        is_last_fragment = (j == len(fragments) - 1)
                        rtp_packet = self._create_rtp_packet(fragment, 28, packet_count, self.rtp_timestamp, marker_bit=is_last_fragment)
                        
                        if hasattr(sock, 'sendto'):
                            sock.sendto(rtp_packet, target)
                        else:
                            sock.send(rtp_packet)
                            
                        logger.debug(f"发送FU-A分片: {j+1}/{len(fragments)}, 大小: {len(rtp_packet)}, marker: {is_last_fragment}")
                        packets_in_frame += 1
                        
                        # 分片间的延迟控制
                        time.sleep(0.001)  # 1ms延迟
                        
                        # 检查发送速率
                        if packet_count % 20 == 0:
                            elapsed = time.time() - start_time
                            if elapsed > 0:
                                current_rate = packet_count / elapsed
                                # 控制发送速率
                                if current_rate > 100:
                                    time.sleep(0.002)
                else:
                    # 单包发送，设置marker bit表示NAL单元结束
                    packet_count += 1
                    rtp_packet = self._create_rtp_packet(nal_data, nal_type, packet_count, self.rtp_timestamp, marker_bit=True)
                    
                    if hasattr(sock, 'sendto'):
                        sock.sendto(rtp_packet, target)
                    else:
                        sock.send(rtp_packet)
                        
                    logger.debug(f"发送NAL类型: {nal_type}, 大小: {len(rtp_packet)}, 时间戳: {self.rtp_timestamp}")
                    packets_in_frame += 1
                    
                    # 单包间的延迟控制
                    time.sleep(0.001)  # 1ms延迟
                
                # 帧结束处理 - 只在帧边界时更新时间戳
                is_frame_end = (i == len(nal_units) - 1 or (i + 1 < len(nal_units) and nal_units[i + 1][0] in [1, 5]))
                if is_frame_end:
                    # 计算帧发送时间
                    frame_elapsed = time.time() - frame_start_time
                    target_frame_time = 1.0 / 25.0  # 25fps = 40ms per frame
                    
                    # 严格控制帧率，确保稳定25fps
                    if frame_elapsed < target_frame_time:
                        sleep_time = target_frame_time - frame_elapsed
                        time.sleep(sleep_time)
                        logger.debug(f"帧率控制延迟: {sleep_time*1000:.1f}ms")
                    
                    # 更新RTP时间戳（只在帧结束时更新） - 确保单调递增
                    old_timestamp = self.rtp_timestamp
                    self.rtp_timestamp += self.frame_duration
                    
                    # 处理时间戳溢出（严格检查）
                    if self.rtp_timestamp >= 0x100000000:
                        self.rtp_timestamp = self.frame_duration
                        logger.info(f"RTP时间戳溢出重置: 从 {old_timestamp} 重置到 {self.rtp_timestamp}")
                    
                    logger.debug(f"帧结束，下一帧时间戳从 {old_timestamp} 更新到: {self.rtp_timestamp}")
                    
                    # 重置帧计数
                    packets_in_frame = 0
                
                # 重置连续错误计数
                consecutive_errors = 0
                
            except Exception as e:
                logger.error(f"发送NAL单元失败 (类型: {nal_type}): {e}")
                consecutive_errors += 1
                if consecutive_errors >= 10:
                    logger.error("连续发送失败过多，退出循环")
                    return False
                    
        # 统计信息
        total_elapsed = time.time() - start_time
        final_rate = packet_count / total_elapsed if total_elapsed > 0 else 0
        success_rate = (packet_count - consecutive_errors) / packet_count * 100 if packet_count > 0 else 0
        logger.info(f"循环{cycle_count + 1}完成: 总计{packet_count}包, 成功率: {success_rate:.1f}%, 平均速率: {final_rate:.1f}包/秒, 总用时: {total_elapsed:.2f}秒")
        return True

    def _fragment_nal_unit(self, nal_data, nal_type):
        """将NAL单元分片以适应MTU限制"""
        # MTU限制（通常1500字节，减去IP头20字节，UDP头8字节，RTP头12字节）
        max_payload_size = 1400  # 使用更保守的值
        
        if len(nal_data) <= max_payload_size:
            # 不需要分片，直接返回原始NAL数据
            return [nal_data]
        
        # 需要分片 - 使用FU-A分片
        fragments = []
        
        # 确保NAL数据是bytes类型且不为空
        if not isinstance(nal_data, bytes) or len(nal_data) < 2:
            logger.error(f"无效的NAL数据格式或长度: {type(nal_data)}, 长度: {len(nal_data) if nal_data else 0}")
            return [nal_data]
        
        # 从原始NAL头中提取信息
        original_nal_header = nal_data[0]
        forbidden_zero_bit = (original_nal_header >> 7) & 0x01
        nal_ref_idc = (original_nal_header >> 5) & 0x03
        original_nal_type = original_nal_header & 0x1F
        
        # 构造FU indicator: F(1) + NRI(2) + Type(5) = 28 (FU-A)
        fu_indicator = (forbidden_zero_bit << 7) | (nal_ref_idc << 5) | 28
        
        # 构造FU header的不同模式
        fu_header_start = 0x80 | original_nal_type   # S=1, E=0, R=0, Type=original_nal_type
        fu_header_middle = original_nal_type          # S=0, E=0, R=0, Type=original_nal_type  
        fu_header_end = 0x40 | original_nal_type     # S=0, E=1, R=0, Type=original_nal_type
        
        # 跳过原始NAL头（第一个字节）
        payload = nal_data[1:]
        payload_size = len(payload)
        fragment_size = max_payload_size - 2  # 减去FU indicator和FU header
        
        offset = 0
        fragment_count = 0
        
        while offset < payload_size:
            fragment_count += 1
            end_offset = min(offset + fragment_size, payload_size)
            fragment_payload = payload[offset:end_offset]
            
            if fragment_count == 1:
                # 第一个片段
                fu_header = fu_header_start
            elif end_offset == payload_size:
                # 最后一个片段
                fu_header = fu_header_end
            else:
                # 中间片段
                fu_header = fu_header_middle
            
            # 构造FU-A包：FU indicator + FU header + 片段数据
            try:
                fragment_data = struct.pack('!BB', fu_indicator, fu_header) + fragment_payload
                fragments.append(fragment_data)
            except Exception as e:
                logger.error(f"构造FU-A片段失败: {e}, fu_indicator={fu_indicator}, fu_header={fu_header}")
                return [nal_data]  # 返回原始数据作为备用
            
            offset = end_offset
        
        logger.debug(f"NAL单元分片: {len(nal_data)} 字节 -> {len(fragments)} 个片段")
        return fragments

    def _parse_h264_nal_units(self, h264_data):
        """解析H.264数据中的NAL单元"""
        logger.info(f"开始解析H.264 NAL单元，数据大小: {len(h264_data):,} 字节")
        
        nal_units = []
        data_len = len(h264_data)
        i = 0
        nal_count = 0
        
        while i < data_len - 4:
            # 查找NAL单元起始码 0x00000001 或 0x000001
            if (h264_data[i:i+4] == b'\x00\x00\x00\x01'):
                start = i + 4
                # 查找下一个起始码
                j = start
                while j < data_len - 4:
                    if (h264_data[j:j+4] == b'\x00\x00\x00\x01' or 
                        h264_data[j:j+3] == b'\x00\x00\x01'):
                        break
                    j += 1
                
                if j > start:
                    nal_unit = h264_data[start:j]
                    if len(nal_unit) > 0:
                        nal_type = nal_unit[0] & 0x1F
                        nal_count += 1
                        logger.debug(f"找到NAL单元 #{nal_count}: 类型={nal_type}, 大小={len(nal_unit)}")
                        nal_units.append((nal_type, nal_unit))
                i = j
            elif (h264_data[i:i+3] == b'\x00\x00\x01'):
                start = i + 3
                # 查找下一个起始码
                j = start
                while j < data_len - 3:
                    if (h264_data[j:j+4] == b'\x00\x00\x00\x01' or 
                        h264_data[j:j+3] == b'\x00\x00\x01'):
                        break
                    j += 1
                
                if j > start:
                    nal_unit = h264_data[start:j]
                    if len(nal_unit) > 0:
                        nal_type = nal_unit[0] & 0x1F
                        nal_count += 1
                        logger.debug(f"找到NAL单元 #{nal_count}: 类型={nal_type}, 大小={len(nal_unit)}")
                        nal_units.append((nal_type, nal_unit))
                i = j
            else:
                i += 1
        
        # 统计NAL单元类型
        type_counts = {}
        for nal_type, _ in nal_units:
            type_counts[nal_type] = type_counts.get(nal_type, 0) + 1
        
        logger.info(f"NAL单元解析完成，总计: {len(nal_units)} 个")
        for nal_type, count in type_counts.items():
            type_name = {
                1: "P帧", 5: "I帧", 6: "SEI", 7: "SPS", 8: "PPS", 9: "AUD"
            }.get(nal_type, f"类型{nal_type}")
            logger.info(f"  {type_name}: {count} 个")
        
        # 检查关键NAL单元
        has_sps = any(nal_type == 7 for nal_type, _ in nal_units)
        has_pps = any(nal_type == 8 for nal_type, _ in nal_units)
        has_idr = any(nal_type == 5 for nal_type, _ in nal_units)
        
        if has_sps and has_pps:
            logger.info("✓ 找到SPS和PPS参数集")
        else:
            logger.warning(f"✗ 缺少关键参数集 - SPS: {has_sps}, PPS: {has_pps}")
        
        if has_idr:
            logger.info("✓ 找到IDR关键帧")
        else:
            logger.warning("✗ 未找到IDR关键帧，可能影响播放")
                
        return nal_units

    def _create_rtp_packet(self, nal_data, nal_type, seq, timestamp, marker_bit=False):
        """创建标准H.264 RTP包"""
        # RTP头部构造
        version = 2
        padding = 0
        extension = 0
        csrc_count = 0
        payload_type = 98  # H.264
        
        # 构造RTP头部
        byte1 = (version << 6) | (padding << 5) | (extension << 4) | csrc_count
        
        # 设置marker bit - 通常在帧结束时设置为1
        marker = 1 if marker_bit else 0
        byte2 = (marker << 7) | payload_type
        
        # 使用struct.pack确保网络字节序
        # 注意：struct.pack的"I"格式本身就是32位无符号整数，会自动处理溢出
        # 避免使用模运算导致时间戳意外倒退
        rtp_header = struct.pack("!BBHII",
            byte1,
            byte2,
            seq % 65536,  # 确保序列号在有效范围内
            timestamp & 0xFFFFFFFF,  # 使用位掩码确保32位范围，避免倒退
            self.ssrc
        )
        
        # 验证并处理NAL数据
        if not isinstance(nal_data, bytes):
            logger.error(f"NAL数据必须是bytes类型，当前类型: {type(nal_data)}")
            return rtp_header
        
        if len(nal_data) == 0:
            logger.warning("NAL数据为空")
            return rtp_header
        
        # 验证NAL单元头部
        try:
            actual_nal_type = nal_data[0] & 0x1f
            if actual_nal_type != nal_type and nal_type != 28:  # 28是FU-A类型
                logger.debug(f"NAL类型不匹配: 期望={nal_type}, 实际={actual_nal_type}")
        except IndexError:
            logger.error("NAL数据太短，无法读取类型")
            return rtp_header
        
        return rtp_header + nal_data